package com.lightjet.macross.base.awf.config;


import com.lightjet.macross.base.awf.domain.BizProcessConfig;
import com.lightjet.macross.base.awf.service.BizProcessConfigService;
import com.lightjet.macross.base.awf.service.IFinishService;
import com.lightjet.macross.base.awf.service.ProcessService;
import com.lightjet.macross.common.dto.ResultDTO;
import com.lightjet.macross.common.util.JwtUtil;
import com.lightjet.macross.common.util.RedisUtil;
import com.lightjet.macross.common.util.SpringUtil;
import io.netty.util.internal.StringUtil;
import lombok.extern.java.Log;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import static com.lightjet.macross.base.awf.config.AWFConstants.*;
import static com.lightjet.macross.base.awf.enums.AWFInfoEnum.*;


/**
 * @author : lijia
 * @version : 1.0 2019-02-21 14:08
 * description :
 */
@Component("processCompleteExecutionListener")
@Log

public class ProcessCompleteExecutionListener implements Serializable,JavaDelegate {
    @Resource
    private RuntimeService runtimeService;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private ProcessService processService;

    @Resource
    private BizProcessConfigService bizProcessConfigService;

    @Resource
    private RedisUtil redisUtil;

    @Override
    public void execute(DelegateExecution delegateExecution) {
        //在处理服务任务前 将流程实例ID存放到 redis 用以表示该流程目前正在进行业务处理 避免在业务处理用时较长的情况下 客户端再次使用taskid 进行任务处理
        if(redisUtil!=null) {
            redisUtil.set("awfp::piid_" + delegateExecution.getProcessInstanceId(), delegateExecution.getId());
        }
        else
        {
            log.info("redisUtil为空，无法进行业务处理防重操作");
        }
        log.info("触发【"+delegateExecution.getCurrentFlowElement().getName()+"】ProcessCompleteExecutionListener"+delegateExecution.getId()+":"+delegateExecution.getProcessInstanceId());
        try
        {
            delegateExecution.setVariable(PREV_SERVICE_NODENAME,delegateExecution.getCurrentFlowElement().getName());
            List<HashMap> formlist = processService.GetPreviousForms(delegateExecution.getProcessInstanceId(), delegateExecution.getCurrentActivityId());

            //首先尝试从数据库获取配置
            BizProcessConfig config = bizProcessConfigService.GetConfigValue(delegateExecution.getProcessDefinitionId(),delegateExecution.getCurrentFlowElement().getId(), BizProcessConfig.ConfigTypes.ASSIGNEEAPI);
            String expression = config==null? (StringUtil.isNullOrEmpty(delegateExecution.getCurrentFlowElement().getDocumentation())?"":delegateExecution.getCurrentFlowElement().getDocumentation())  : config.getConfigvalue();

            //if(delegateExecution.getCurrentFlowElement().getDocumentation()!=null)
            if(!StringUtil.isNullOrEmpty(expression))
            {
                //首先尝试从数据库获取配置
//                BizProcessConfig config = bizProcessConfigService.GetConfigValue(delegateExecution.getProcessDefinitionId(),delegateExecution.getCurrentFlowElement().getId(), BizProcessConfig.ConfigTypes.FINISHAPI);
//                String expression = config==null? delegateExecution.getCurrentFlowElement().getDocumentation() : config.getConfigvalue();
                String _originator = delegateExecution.getVariable("_originator")==null?"":delegateExecution.getVariable("_originator").toString();
                //获取表达式
                //如果表达式包含@
                if(expression.contains("@")) {
                    String[] expressions = expression.split("@");
                    String handler = expressions[1];
                    ResultDTO result;
                    if(!StringUtil.isNullOrEmpty(handler)) {
                        String[] handlerexp = handler.split("#");
                        handler = handlerexp[0];
                        String args = handlerexp.length>1?handlerexp[1]:"";
                        switch (expressions[0].toLowerCase()) {
                            case "webapi":
                                handler = handler + (handler.contains("?") ? "&" : "?") + ("originator=" + _originator) +"&nodename="+ delegateExecution.getCurrentFlowElement().getName() +"args="+ args;
                                HttpHeaders headers = new HttpHeaders();
                                headers.add("exchange-token", JwtUtil.signWithClaims(30,"802sastcasc!",AUTH_TOKEN));
                                HttpEntity<List<HashMap>> httpEntity = new HttpEntity<List<HashMap>>(formlist,headers);
                                result =  new RestTemplate().postForObject(handler, httpEntity, ResultDTO.class);
                                break;
                            case "bean":
                                IFinishService h = SpringUtil.getBean(handler, IFinishService.class);
                                result = h.Handle(formlist,_originator,delegateExecution.getCurrentFlowElement().getName(),args);
                                break;
                            case "class":
                                try {
                                    Class assigneeClass = Class.forName(handler);
                                    Object obj = assigneeClass.newInstance();
                                    if (obj instanceof IFinishService)
                                    {
                                        result =((IFinishService) obj).Handle(formlist,_originator,delegateExecution.getCurrentFlowElement().getName(),args);
                                    }
                                    else
                                    {
                                        throw new RuntimeException(MessageFormat.format(PROCESSFINISH_HANDLEUNIMPLEMENTED_ERROR.toString(),delegateExecution.getProcessInstanceId(),handler));
                                    }

                                }
                                catch(Exception e)
                                {
                                    log.info(MessageFormat.format(PROCESSFINISH_HANDLERPARSE_ERROR.toString(),delegateExecution.getProcessInstanceId(),handler,e.getMessage()));
                                    throw new RuntimeException(MessageFormat.format(PROCESSFINISH_HANDLERPARSE_ERROR.toString(),delegateExecution.getProcessInstanceId(),handler,e.getMessage()));
                                }
                                break;

                            default:
                                log.info(MessageFormat.format(PROCESSFINISH_HANDLEUNKOWN_ERROR.toString(),delegateExecution.getProcessInstanceId(),handler));
                                throw new RuntimeException(MessageFormat.format(PROCESSFINISH_HANDLEUNKOWN_ERROR.toString(),delegateExecution.getProcessInstanceId(),handler));

                        }
                    }
                    else
                    {
                        log.info(MessageFormat.format(PROCESSFINISH_HANDLEREMPTY_ERROR.toString(),delegateExecution.getProcessInstanceId(),expression));
                        throw new RuntimeException(MessageFormat.format(PROCESSFINISH_HANDLEREMPTY_ERROR.toString(),delegateExecution.getProcessInstanceId(),expression));
                    }
                    if (!result.isSuccess()) {
                        throw new RuntimeException(result.getMessage());
                    }
                    /*String handler = delegateExecution.getCurrentFlowElement().getDocumentation();

                    handler = handler + (handler.contains("?") ? "&" : "?") + ("originator=" + _originator);
                    processService.ProcessNodeForm(delegateExecution.getProcessInstanceId(), delegateExecution.getCurrentActivityId());
                    List<HashMap> formlist = processService.GetPreviousForms(delegateExecution.getProcessInstanceId(), delegateExecution.getCurrentActivityId());
                    ResultDTO res = restTemplate.postForObject(handler, formlist, ResultDTO.class);
                    if (!res.isSuccess()) {
                        throw new RuntimeException(res.getMessage());
                    }*/
                }
                else
                {
                    log.info(MessageFormat.format(PROCESSFINISH_EXPRESSION_ERROR.toString(),delegateExecution.getProcessInstanceId(),expression));
                    throw new RuntimeException(MessageFormat.format(PROCESSFINISH_EXPRESSION_ERROR.toString(),delegateExecution.getProcessInstanceId(),expression));

                }

            }
            delegateExecution.setVariable(FLAG_VARIABLE,DEFAULT_APPROVEFLAG);

            //throw new RuntimeException("测试异常处理！");

        }
        catch (Exception e)
        {
            delegateExecution.setVariable(FLAG_VARIABLE,"f");
            delegateExecution.setVariable(SERVICENODE_ERROR_VARIABLE,MessageFormat.format(TASKFINISH_BIZ_ERROR.toString(),delegateExecution.getProcessInstanceId(),e.getMessage()));
            log.info(MessageFormat.format(TASKFINISH_BIZ_ERROR.toString(),delegateExecution.getProcessInstanceId(),e.getMessage()));
        }
        finally {
            if(redisUtil!=null) {
                redisUtil.DeleteKeys("awfp::piid_" + delegateExecution.getProcessInstanceId());
            }
            else
            {
                log.info("redisUtil为空，无法进行业务处理防重操作");
            }
        }

    }
}
